/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2009-2020 Rock Mao
* creator : Rock Mao
* created : 2009-5-3   22:29
* filename: LaborPoint2.h
-----------------------------------------------------------------------------
*/

#ifndef __XVECTOR_2D_INLINE_INCLUDE__
#define __XVECTOR_2D_INLINE_INCLUDE__

#include "../LaborCoreDef.h"


NAMESPACE_LABOR3D_BEGIN

template <typename _Type> class LABORCORE_API TPoint2
{
public:
	typedef _Type value_type ;
public:
	TPoint2(){};
	~TPoint2(){};
	TPoint2(_Type _v){	x = _v ; y = _v;  }
	TPoint2(_Type _x,_Type _y){x = _x ; y = _y; }
	TPoint2(TPoint3<_Type>& v){	this->x = v.x;	this->y = v.y;}
	TPoint2(TPoint4<_Type>& v){	this->x = v.x;	this->y = v.y;}
	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	void              add(const TPoint2<_Type>& rv)
	{
		x += rv.x; 
		y += rv.y;
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	void              sub(const TPoint2<_Type>& rv)
	{
		x -= rv.x; 
		y -= rv.y;
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	void              mul(lscalar s)
	{
		x = (_Type)(x *s); 
		y = (_Type)(y *s);
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	value_type             fabs()  const     
	{ 
		return (value_type)xsqrt( (lscalar)(x * x + y * y) ) ;
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	value_type             len()  const     
	{ 
		return (value_type)xsqrt( value_type(x * x + y * y) ) ;
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	value_type             squardlen()  const     
	{
		return (value_type)(x * x + y * y) ;
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	void              normalize()
	{
		value_type len = (value_type)xsqrt( (value_type)(x * x + y * y) ) ; 
		x= _Type(x/len);
		y= _Type(y/len); 
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	void              normalize(TPoint2<_Type> &vout)
	{
		value_type len = (value_type)xsqrt( value_type(x * x + y * y) ) ; 
		vout.x = (_Type)(x/len); vout.y = (_Type)(y/len);
	}


	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>         operator +(const TPoint2<_Type>& v)  const     
	{ 
		return TPoint2<_Type>(v.x + x, v.y + y);
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>         operator -(const TPoint2<_Type>& v)  const     
	{ 
		return TPoint2<_Type>(x - v.x, y - v.y);
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>         operator *(const value_type s)  const     
	{ 
		return TPoint2<_Type>(  (_Type)(x * s),  (_Type)(y * s) );
	}


	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	bool             operator ==(const TPoint2<_Type>& v)  const      
	{
		return (v.x == x && v.y == y); 
	}


	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	bool             isZero()  const     
	{
		return ( numeric_equal(x , (_Type)0) && numeric_equal(y ,  (_Type)0) );
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	_Type            dp(const TPoint2<_Type>& v)  const     
	{
		return  _Type(v.x*x + v.y *y) ;
	}

    _Type            cp(const TPoint2<_Type>& v)  const     
    {
        return x * v.y - v.x * y;
    }

	void            cp(const TPoint2<_Type>& v , TPoint3<_Type>& _out)  const     
	{
		_out.x = 0;
		_out.y = 0;
		_out.z = x * v.y - v.x * y;
	}


	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>&        operator +=(const TPoint2<_Type>& v)
	{ 
		x += v.x ; y += v.y ; 
		return *this; 
	}


	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>&        operator -=(const TPoint2<_Type>& v)
	{ 
		x -= v.x ; y -= v.y ; 
		return *this; 
	}

	//-----------------------------------------------------
	//
	//-----------------------------------------------------
	TPoint2<_Type>&        operator *=(lscalar s)
	{ 
		x =  (_Type)(x *s ); 
		y =  (_Type)(y *s ); 
		return *this; 
	}

	operator _Type* (){ return v ; }
public:
	union
	{
		struct
		{
			_Type x,y;
		};
		struct
		{
			_Type s,t;
		};
		_Type v[2];
	};
};
template <typename T> TPoint2<T> operator * (const T& v1 , const TPoint2<T>& v2)
{
    TPoint2<T> _ret;
    _ret.x = v1 * v2.x;
    _ret.y = v1 * v2.y;
    return _ret;
}

template <typename T> TPoint2<T> operator * (const TPoint2<T>& v1 , const TPoint2<T>& v2)
{
    TPoint2<T> _ret;
    _ret.x = v1.x * v2.x;
    _ret.y = v1.y * v2.y;
    return _ret;
}

//typedef TPoint2<lscalar>         CLPoint2;
//typedef TPoint2<unsigned int>  CLPoint2ui;
//typedef TPoint2<int>           CLPoint2i;

NAMESPACE_LABOR3D_END



#endif


